/* jslight_c.js -- C highlighter for jslight */
/* Copyright 2007 Rici Lake. */
/* You may use this software under the terms of the MIT license
 * as shown at http://www.opensource.org/licenses/mit-license.php
 */

if (!this.jslight) {this.jslight = {"language":{}}; }
(function() {
  jslight.language.c = {}

  var words = {}

/* This list is probably not complete; it certainly doesn't include c++. I took
 * it out of the c.vim syntax file, but it needs to be verified against c, c99,
 * gnu extensions, and POSIX
 */
  jslight.addAnnotations(words,[
  [ "statement",  [ "goto", "break", "return", "continue", "asm", "__asm__"]],
  [ "label",      [ "case", "default"]],
  [ "conditional",[ "if", "else", "switch"]],
  [ "repeat",     [ "do", "for", "while"]],
  [ "operator",   [ "sizeof", "typeof", "__real__", "__imag__"]],
  [ "type",       [ "long", "short", "signed", "unsigned", "int", "void",
                    "float", "double", "bool", "complex",
                    "struct", "union", "enum", "typedef",
                    "static", "register", "auto", "volatile", "extern", "const",
                    "inline", "restrict",
                    "__label__", "__complex__", "__volatile__", "__attribute__",
                    "size_t", "ssize_t", "wchar_t", "ptrdiff_t", "sig_atomic_t", "fpos_t",
                    "clock_t", "time_t", "va_list", "jmp_buf", "FILE", "DIR", "div_t", "ldiv_t",
                    "mbstate_t", "wctrans_t", "wint_t", "wctype_t",
                    "int8_t", "int16_t", "int32_t", "int64_t",
                    "uint8_t", "uint16_t", "uint32_t", "uint64_t",
                    "int_least8_t", "int_least16_t", "int_least32_t", "int_least64_t",
                    "uint_least8_t", "uint_least16_t", "uint_least32_t", "uint_least64_t",
                    "int_fast8_t", "int_fast16_t", "int_fast32_t", "int_fast64_t",
                    "uint_fast8_t", "uint_fast16_t", "uint_fast32_t", "uint_fast64_t",
                    "intptr_t", "uintptr_t", "intmax_t", "uintmax_t"]],
  [ "constant",   [ "__GNUC__", "__FUNCTION__", "__PRETTY_FUNCTION__", "__func__",
                    "__LINE__", "__FILE__", "__DATE__", "__TIME__", "__STDC__",
                    "CHAR_BIT", "MB_LEN_MAX", "MB_CUR_MAX",
                    "UCHAR_MAX", "UINT_MAX", "ULONG_MAX", "USHRT_MAX",
                    "CHAR_MIN", "INT_MIN", "LONG_MIN", "SHRT_MIN",
                    "CHAR_MAX", "INT_MAX", "LONG_MAX", "SHRT_MAX",
                    "SCHAR_MIN", "SINT_MIN", "SLONG_MIN", "SSHRT_MIN",
                    "SCHAR_MAX", "SINT_MAX", "SLONG_MAX", "SSHRT_MAX",
                    "__func__",
                    "LLONG_MAX", "ULLONG_MAX",
                    "INT8_MIN", "INT16_MIN", "INT32_MIN", "INT64_MIN",
                    "INT8_MAX", "INT16_MAX", "INT32_MAX", "INT64_MAX",
                    "UINT8_MAX", "UINT16_MAX", "UINT32_MAX", "UINT64_MAX",
                    "INT_LEAST8_MIN", "INT_LEAST16_MIN", "INT_LEAST32_MIN", "INT_LEAST64_MIN",
                    "INT_LEAST8_MAX", "INT_LEAST16_MAX", "INT_LEAST32_MAX", "INT_LEAST64_MAX",
                    "UINT_LEAST8_MAX", "UINT_LEAST16_MAX", "UINT_LEAST32_MAX", "UINT_LEAST64_MAX",
                    "INT_FAST8_MIN", "INT_FAST16_MIN", "INT_FAST32_MIN", "INT_FAST64_MIN",
                    "INT_FAST8_MAX", "INT_FAST16_MAX", "INT_FAST32_MAX", "INT_FAST64_MAX",
                    "UINT_FAST8_MAX", "UINT_FAST16_MAX", "UINT_FAST32_MAX", "UINT_FAST64_MAX",
                    "INTPTR_MIN", "INTPTR_MAX", "UINTPTR_MAX",
                    "INTMAX_MIN", "INTMAX_MAX", "UINTMAX_MAX",
                    "PTRDIFF_MIN", "PTRDIFF_MAX", "SIG_ATOMIC_MIN", "SIG_ATOMIC_MAX",
                    "SIZE_MAX", "WCHAR_MIN", "WCHAR_MAX", "WINT_MIN", "WINT_MAX",
                    "FLT_RADIX", "FLT_ROUNDS",
                    "FLT_DIG", "FLT_MANT_DIG", "FLT_EPSILON",
                    "DBL_DIG", "DBL_MANT_DIG", "DBL_EPSILON",
                    "LDBL_DIG", "LDBL_MANT_DIG", "LDBL_EPSILON",
                    "FLT_MIN", "FLT_MAX", "FLT_MIN_EXP", "FLT_MAX_EXP",
                    "FLT_MIN_10_EXP", "FLT_MAX_10_EXP",
                    "DBL_MIN", "DBL_MAX", "DBL_MIN_EXP", "DBL_MAX_EXP",
                    "DBL_MIN_10_EXP", "DBL_MAX_10_EXP",
                    "LDBL_MIN", "LDBL_MAX", "LDBL_MIN_EXP", "LDBL_MAX_EXP",
                    "LDBL_MIN_10_EXP", "LDBL_MAX_10_EXP",
                    "HUGE_VAL", "CLOCKS_PER_SEC", "NULL",
                    "LC_ALL", "LC_COLLATE", "LC_CTYPE", "LC_MONETARY",
                    "LC_NUMERIC", "LC_TIME",
                    "SIG_DFL", "SIG_ERR", "SIG_IGN",
                    "SIGFPE", "SIGILL", "SIGHUP", "SIGINT", "SIGSEGV", "SIGTERM",
                    "SIGABRT", "SIGALRM", "SIGCHLD", "SIGCONT", "SIGFPE", "SIGHUP",
                    "SIGILL", "SIGINT", "SIGKILL", "SIGPIPE", "SIGQUIT", "SIGSEGV",
                    "SIGSTOP", "SIGTERM", "SIGTRAP", "SIGTSTP", "SIGTTIN", "SIGTTOU",
                    "SIGUSR1", "SIGUSR2",
                    "_IOFBF", "_IOLBF", "_IONBF", "BUFSIZ", "EOF", "WEOF",
                    "FOPEN_MAX", "FILENAME_MAX", "L_tmpnam",
                    "SEEK_CUR", "SEEK_END", "SEEK_SET",
                    "TMP_MAX", "stderr", "stdin", "stdout",
                    "EXIT_FAILURE", "EXIT_SUCCESS", "RAND_MAX",
                    "E2BIG", "EACCES", "EAGAIN", "EBADF", "EBADMSG", "EBUSY",
                    "ECANCELED", "ECHILD", "EDEADLK", "EDOM", "EEXIST", "EFAULT",
                    "EFBIG", "EILSEQ", "EINPROGRESS", "EINTR", "EINVAL", "EIO", "EISDIR",
                    "EMFILE", "EMLINK", "EMSGSIZE", "ENAMETOOLONG", "ENFILE", "ENODEV",
                    "ENOENT", "ENOEXEC", "ENOLCK", "ENOMEM", "ENOSPC", "ENOSYS",
                    "ENOTDIR", "ENOTEMPTY", "ENOTSUP", "ENOTTY", "ENXIO", "EPERM",
                    "EPIPE", "ERANGE", "EROFS", "ESPIPE", "ESRCH", "ETIMEDOUT", "EXDEV",
                    "M_E", "M_LOG2E", "M_LOG10E", "M_LN2", "M_LN10", "M_PI", "M_PI_2", "M_PI_4",
                    "M_1_PI", "M_2_PI", "M_2_SQRTPI", "M_SQRT2", "M_SQRT1_2",
                    "true", "false"]]
  ]);

  /* We construct a single regular expression which matches every possible lexeme.
   * We make no attempt to deal with trigraphs, digraphs, or \ outside of preprocessor defs
   *
   * 1: preprocessing directives (possibly multiline)  2: whitespace  3: comments
   * 4: strings     5: preprocessing numbers           6: identifiers 7: valid op char
   * 8: error
   *
   * TODO: handle labels.
   */
  var lex = /(^\s*#(?:.|\\\n)*)|([\x20\t]+|\n+)|(\/\/.*|\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/)|(L?(?:"(?:[^\\"]|\\(?:.|\s))*"|'(?:[^\\']|\\(?:.|\s))*'))|(\.?[0-9](?:[0-9a-df-oq-zA-DF-OQ-Z_.]|[eEpP][+-]?)*)|([a-zA-Z_][\w_]*)|([!~%()*+,.\/.:;=?[\]^{|}#-]|&(?:lt|gt|amp);)|(.)/gm;

  var numpat = /^[1-9]\d*(e[+-]?\d+[fl]?|ul?l?|ll?u?)?$|^(\d+\.|\.\d)\d*(e[+-]?\d+)?[fl]?$|^0x([0-9a-f]+(ul?l?|ll?u?|(\.[0-9a-f]*)?(p[+-]?\d+[fl]?)?)?|\.[0-9a-f]+(p[+-]?\d+[fl]?)?)$|^0[0-7]*(ul?l?|ll?u?)?$/i;
  function highlightPreproc(m) { return jslight.annotate(m, "preproc"); }  // For now
  function highlightNumber(m) { return jslight.annotate(m, numpat.test(m) ? "constant" : "error"); }

  function highlightLexeme(m, a1, a2, a3, a4, a5, a6, a7, a8) {
    if (a1) return highlightPreproc(m);
    else if (a2) return jslight.annotate(m);
    else if (a3) return jslight.annotate(m, "comment");
    else if (a4) return jslight.annotate(m, "constant");
    else if (a5) return highlightNumber(m);
    else if (a6) return jslight.annotate(m, words[m]);
    else if (a7) return jslight.annotate(m); // No annotation for op chars yet
    else return jslight.annotate(m, "error");
  }

  function highlight(s) { return s.replace(lex, highlightLexeme); }

  jslight.language.c.getHighlighter = function() { return highlight; }
})()
